#include "stm32f1xx_hal.h"
#include "loopsys.h"
#include "console.h"

#define STM32_UART_TX_USE_DMA
#define STM32_UART_RX_USE_DMA
#define STM32_UART_POLL_TIMEOUT 100

extern UART_HandleTypeDef huart1;
UART_HandleTypeDef *console_uart = &huart1;

#ifdef LOOPSYS_ENABLE_SYSTIME
void SysTick_Handler(void)
{
    loopsys_tick_increase();
}
#endif

#ifdef CONSOLE_USE_ASNYC_SEND
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == console_uart)
    {
        console_send_done();
    }
}

static int32_t stm32_uart_start_send(uint8_t *buff, int32_t size)
{
    HAL_StatusTypeDef  ret;

#ifdef STM32_UART_TX_USE_DMA
    ret = HAL_UART_Transmit_DMA(console_uart, buff, size);
#else
    ret = HAL_UART_Transmit_IT(console_uart, buff, size);
#endif

    return (ret == HAL_OK) ? 0 : -1;
}

static int32_t stm32_uart_stop_send(void)
{
    HAL_StatusTypeDef ret;

    ret = HAL_UART_AbortTransmit(console_uart);

    return (ret == HAL_OK) ? 0 : -1;
}
#else
static int32_t stm32_uart_poll_send(uint8_t *buff, int32_t size)
{
    HAL_StatusTypeDef ret;

    ret = HAL_UART_Transmit(console_uart, (uint8_t *)buff, size, STM32_UART_POLL_TIMEOUT);

    return (ret == HAL_OK) ? size : 0;
}
#endif

#ifdef CONSOLE_USE_ASNYC_RECV
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == console_uart)
    {
        console_recv_done();
    }
}

static int32_t stm32_uart_start_recv(uint8_t *buff, int32_t size)
{
    HAL_StatusTypeDef ret;

#ifdef STM32_UART_RX_USE_DMA
    ret = HAL_UART_Receive_DMA(console_uart, buff, size);
#else
    ret = HAL_UART_Receive_IT(console_uart, buff, size);
#endif

    return (ret == HAL_OK) ? 0 : -1;
}

static int32_t stm32_uart_stop_recv(void)
{
    HAL_StatusTypeDef ret;

    ret = HAL_UART_AbortReceive(console_uart);

    return (ret == HAL_OK) ? 0 : -1;
}

static int32_t stm32_uart_recv_count(void)
{
    return console_uart->RxXferSize - __HAL_DMA_GET_COUNTER(console_uart->hdmarx);
}

#else
static int32_t stm32_uart_poll_recv(uint8_t *buff, int32_t size)
{
    HAL_StatusTypeDef  ret;

    ret = HAL_UART_Receive(console_uart, (uint8_t *)buff, size, STM32_UART_POLL_TIMEOUT * size);

    return (ret == HAL_OK) ? size : 0;
}

#endif

console_dev_ops_t stm32_console_ops = {
#ifdef CONSOLE_USE_ASNYC_SEND
    .start_send = stm32_uart_start_send,
    .stop_send  = stm32_uart_stop_send,
#else
    .poll_send  = stm32_uart_poll_send,
#endif

#ifdef CONSOLE_USE_ASNYC_RECV
    .start_recv = stm32_uart_start_recv,
    .stop_recv  = stm32_uart_stop_recv,
    .recv_count = stm32_uart_recv_count,
#else
    .poll_recv  = stm32_uart_poll_recv,
#endif
};
